
package system.communication;
import java.io.BufferedReader;
import java.io.IOException;
import system.ui.Engine;

/**
 * This Listener reads single messages from the socket's output buffer and sends out
 * the messages to their respective lists in the Monitor for it's Threads run method.
 * 
 * @author elliot
 */
public class MessageListener extends Thread
{
    public static boolean waiting;
    public BufferedReader br;
    private boolean stop = false;
    private Message currentMessage;
    private SensorNotifier sn;
    private HandControlMessageNotifier hcn;
    private HandController hc1;
    private HandController hc2;

    public HandController getHC(int id)
    {
        if (id == 1)
        {
            return hc1;
        }
        else
        {
            return hc2;
        }
    }
    
    public MessageListener(BufferedReader br)
    {
        this.br = br;
        try
        {
            if(br.ready())
            {
                while(br.ready())
                {
                    System.out.println("Cleared from br: " + br.read());
                }
            }
        }
        catch(IOException ex)
        {
            System.err.println(ex.getMessage());
        }
        sn = null;
        hcn = null;
        hc1 = null;
        hc2 = null;
    }

    /**
     * Registers the first hand controller.
     *
     * Must be called before any queries are made to the hand controller.
     * @param hc1 the hand controller to register as hand control 1.
     */
    public void registerHC1(HandController hc1)
    {
        this.hc1 = hc1;
    }

    /**
     * Registers the second hand controller.
     *
     * Must be called before any queries are made to the hand controller.
     * @param hc2 the second hand controller to register.
     */
    public void registerHC2(HandController hc2)
    {
        this.hc2 = hc2;
    }

    @Override
    public void run()
    {
        try
        {
            while(!stop)
            {
                String line = readLine(br).trim();
                if (!line.equals(""))
                {
                    System.out.println(line);
                    currentMessage = new Message(line);
                    switch(currentMessage.getType())
                    {
                        case BLOCK:
                            Monitor.blockMessages.addFirst(currentMessage);
                            break;
                        case SWITCH:
                            Monitor.switchMessages.addFirst(currentMessage);
                            break;
                        case HANDCONTROL:
                            Monitor.handControlMessages.addFirst(currentMessage);
                            if (hcn == null)
                            {
                                HandControlMessageNotifier checkHandControlMessages 
                                        = new HandControlMessageNotifier(
                                        hc1, hc2);
                                checkHandControlMessages.setName("Hand Control Notifier");
                                checkHandControlMessages.start();
                            }
                            break;
                        case SENSOR:
                            Monitor.sensorMessages.addFirst(currentMessage);
                            if (sn == null)
                            {
                                sn = new SensorNotifier();
                                sn.start();
                            }
                            break;
                        case LED:
                            Monitor.ledMessages.addFirst(currentMessage);
                            break;
                        default:
                            Monitor.otherMessages.addFirst(currentMessage);
                    }
                    Thread.sleep(250);
                    if(Monitor.waiting)
                    {
                        Monitor.getInstance().notifyForResponse();
                    }
                    Engine.getInstance().postMessage(currentMessage, false);
                }

            }
            try
            {
                br.close();
            }
            catch (IOException ioe)
            {
                System.out.println("ending " + ioe);
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
            System.out.println(e);
        }
    }

    public void end()
    {
       stop = true;
       if (sn != null)
       {
           sn.end();
       }
    }

    public synchronized void sensorNotifierDeath()
    {
        sn = null;
    }

    public synchronized void handControllerMessageNotifierDeath()
    {
        hcn = null;
    }

    private String readLine(BufferedReader br) throws IOException
    {
        String strtemp = "";
        char x;
        boolean breaker = false;
        while (br.ready() && stop == false)
        {
            x = (char) br.read();
            strtemp += x;

            if (x == '}')
            {
                breaker = true;
                break;
            }
        }
        return strtemp;
    }

}
